Clear correct area
authorCody Russell <bratsche@src.gnome.org>
Mon, 30 Apr 2007 15:29:16 +0000 (15:29 +0000)
committerCody Russell <bratsche@src.gnome.org>
Mon, 30 Apr 2007 15:29:16 +0000 (15:29 +0000)
svn path=/trunk/; revision=17737

ChangeLog
gdk/win32/gdkwindow-win32.c

index 3db567bca634c803a4f15598e1087ca94daa63ce..67e5ab1d59e3f40f843cbe9945519e49508ccfec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-04-30  Cody Russell  <bratsche@gnome.org>
+
+       * gdk/win32/gdkwindow-win32.c: Reintroduced erase_background(),
+       but now we're calling it from _gdk_windowing_window_clear_area()
+       instead of from the WM_ERASEBKGND event.  Also fixes the area
+       that is cleared so that it is not an extra row and column too
+       large.  (Neil Roberts, #415681)
+
 2007-04-30  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtktextview.c: Allow indents to be negative.  (#Bug 434308)
index 75d944d2d786915124ea812ecc94c44c0f7da6f8..631d4200d1bc3e043f7d226d4ddae7471e96706f 100644 (file)
@@ -1402,6 +1402,139 @@ gdk_window_reparent (GdkWindow *window,
   _gdk_window_init_position (GDK_WINDOW (window_private));
 }
 
+static void
+erase_background (GdkWindow *window,
+                 HDC        hdc)
+{
+  HDC bgdc = NULL;
+  HBRUSH hbr = NULL;
+  HPALETTE holdpal = NULL;
+  RECT rect;
+  COLORREF bg;
+  GdkColormap *colormap;
+  GdkColormapPrivateWin32 *colormap_private;
+  int x, y;
+  int x_offset, y_offset;
+  
+  if (((GdkWindowObject *) window)->input_only ||
+      ((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG ||
+      GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+    {
+      return;
+    }
+
+  colormap = gdk_drawable_get_colormap (window);
+
+  if (colormap &&
+      (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
+       colormap->visual->type == GDK_VISUAL_STATIC_COLOR))
+    {
+      int k;
+         
+      colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
+
+      if (!(holdpal = SelectPalette (hdc,  colormap_private->hpal, FALSE)))
+        WIN32_GDI_FAILED ("SelectPalette");
+      else if ((k = RealizePalette (hdc)) == GDI_ERROR)
+       WIN32_GDI_FAILED ("RealizePalette");
+      else if (k > 0)
+       GDK_NOTE (COLORMAP, g_print ("erase_background: realized %p: %d colors\n",
+                                    colormap_private->hpal, k));
+    }
+  
+  x_offset = y_offset = 0;
+  while (window && ((GdkWindowObject *) window)->bg_pixmap == GDK_PARENT_RELATIVE_BG)
+    {
+      /* If this window should have the same background as the parent,
+       * fetch the parent. (And if the same goes for the parent, fetch
+       * the grandparent, etc.)
+       */
+      x_offset += ((GdkWindowObject *) window)->x;
+      y_offset += ((GdkWindowObject *) window)->y;
+      window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
+    }
+  
+  if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+    {
+      /* Improves scolling effect, e.g. main buttons of testgtk */
+      return;
+    }
+
+  GetClipBox (hdc, &rect);
+
+  if (((GdkWindowObject *) window)->bg_pixmap == NULL)
+    {
+      bg = _gdk_win32_colormap_color (GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->colormap,
+                                     ((GdkWindowObject *) window)->bg_color.pixel);
+      
+      if (!(hbr = CreateSolidBrush (bg)))
+       WIN32_GDI_FAILED ("CreateSolidBrush");
+      else if (!FillRect (hdc, &rect, hbr))
+       WIN32_GDI_FAILED ("FillRect");
+      if (hbr != NULL)
+       DeleteObject (hbr);
+    }
+  else if (((GdkWindowObject *) window)->bg_pixmap != GDK_NO_BG)
+    {
+      GdkPixmap *pixmap = ((GdkWindowObject *) window)->bg_pixmap;
+      GdkPixmapImplWin32 *pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
+      
+      if (x_offset == 0 && y_offset == 0 &&
+         pixmap_impl->width <= 8 && pixmap_impl->height <= 8)
+       {
+         if (!(hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (pixmap))))
+           WIN32_GDI_FAILED ("CreatePatternBrush");
+         else if (!FillRect (hdc, &rect, hbr))
+           WIN32_GDI_FAILED ("FillRect");
+         if (hbr != NULL)
+           DeleteObject (hbr);
+       }
+      else
+       {
+         HGDIOBJ oldbitmap;
+
+         if (!(bgdc = CreateCompatibleDC (hdc)))
+           {
+             WIN32_GDI_FAILED ("CreateCompatibleDC");
+             return;
+           }
+         if (!(oldbitmap = SelectObject (bgdc, GDK_PIXMAP_HBITMAP (pixmap))))
+           {
+             WIN32_GDI_FAILED ("SelectObject");
+             DeleteDC (bgdc);
+             return;
+           }
+         x = -x_offset;
+         while (x < rect.right)
+           {
+             if (x + pixmap_impl->width >= rect.left)
+               {
+                 y = -y_offset;
+                 while (y < rect.bottom)
+                   {
+                     if (y + pixmap_impl->height >= rect.top)
+                       {
+                         if (!BitBlt (hdc, x, y,
+                                      pixmap_impl->width, pixmap_impl->height,
+                                      bgdc, 0, 0, SRCCOPY))
+                           {
+                             WIN32_GDI_FAILED ("BitBlt");
+                             SelectObject (bgdc, oldbitmap);
+                             DeleteDC (bgdc);
+                             return;
+                           }
+                       }
+                     y += pixmap_impl->height;
+                   }
+               }
+             x += pixmap_impl->width;
+           }
+         SelectObject (bgdc, oldbitmap);
+         DeleteDC (bgdc);
+       }
+    }
+}
+
 void
 _gdk_windowing_window_clear_area (GdkWindow *window,
                                  gint       x,
@@ -1428,8 +1561,8 @@ _gdk_windowing_window_clear_area (GdkWindow *window,
                               GDK_WINDOW_HWND (window),
                               width, height, x, y));
       hdc = GetDC (GDK_WINDOW_HWND (window));
-      IntersectClipRect (hdc, x, y, x + width + 1, y + height + 1);
-      SendMessageW (GDK_WINDOW_HWND (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
+      IntersectClipRect (hdc, x, y, x + width, y + height);
+      erase_background (window, hdc);
       GDI_CALL (ReleaseDC, (GDK_WINDOW_HWND (window), hdc));
     }
 }
@@ -1445,6 +1578,7 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window,
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
+      HDC hdc;
       RECT rect;
 
       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area_e: %p: "
@@ -1452,10 +1586,18 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window,
                               GDK_WINDOW_HWND (window),
                               width, height, x, y));
 
+      /* The background should be erased before the expose event is
+        generated */
+      hdc = GetDC (GDK_WINDOW_HWND (window));
+      IntersectClipRect (hdc, x, y, x + width, y + height);
+      erase_background (window, hdc);
+      GDI_CALL (ReleaseDC, (GDK_WINDOW_HWND (window), hdc));
+
       rect.left = x;
-      rect.right = x + width + 1;
+      rect.right = x + width;
       rect.top = y;
-      rect.bottom = y + height + 1;
+      rect.bottom = y + height;
+
       GDI_CALL (InvalidateRect, (GDK_WINDOW_HWND (window), &rect, TRUE));
       UpdateWindow (GDK_WINDOW_HWND (window));
     }